use crate::{error::AppError, utils::signature};
use serde::{Deserialize, Serialize};
use std::{
    path::Path,
    process::Command,
    collections::HashMap
};

#[derive(Debug, Serialize, Deserialize)]
pub struct DeltaPackage {
    pub base_version: String,
    pub target_version: String,
    pub diffs: HashMap<String, Vec<u8>>, // 路径 → bsdiff 二进制差异
}

impl DeltaPackage {
    pub fn create(base: &Path, target: &Path) -> Result<Self, AppError> {
        let mut diffs = HashMap::new();
        
        // 遍历文件生成差异
        for entry in walkdir::WalkDir::new(target) {
            let entry = entry?;
            if entry.file_type().is_file() {
                let rel_path = entry.path().strip_prefix(target)?;
                let base_file = base.join(rel_path);
                
                // 生成 bsdiff
                let diff = Command::new("bsdiff")
                    .arg(base_file)
                    .arg(entry.path())
                    .output()?;
                
                diffs.insert(rel_path.to_str().unwrap().to_string(), diff.stdout);
            }
        }
        
        Ok(Self {
            base_version: read_version(base)?,
            target_version: read_version(target)?,
            diffs,
        })
    }

    pub fn apply(&self, base: &Path, output: &Path) -> Result<(), AppError> {
        for (rel_path, diff) in &self.diffs {
            let base_file = base.join(rel_path);
            let target_file = output.join(rel_path);
            
            // 应用 bspatch
            Command::new("bspatch")
                .arg(base_file)
                .arg(&target_file)
                .arg("/dev/stdin")
                .stdin(std::process::Stdio::piped())
                .spawn()?
                .stdin.unwrap().write_all(diff)?;
        }
        Ok(())
    }
}